﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using DMHelper.Models;
using System.Xml.Linq;
using System.Web.Hosting;

namespace DMHelper.Models
{
    public class DDSheet
    {
        public String SheetID;

        public HeadContainer head = new HeadContainer();
        public CombatContainer combat = new CombatContainer();
        public ACCContainer ac = new ACCContainer();
        public EquipmentContainer equipment = new EquipmentContainer();
        public FeatContainers feats = new FeatContainers();
        public LanguageContainer language = new LanguageContainer();
        public MagicContainer magic = new MagicContainer();
        public StatsContainer stats = new StatsContainer();
        public SpellsContainer spells = new SpellsContainer();
        
        public SkillsContainer skills;
        public SavingThrowsContainer savingThrows;

        public DDSheet()
        {
            SheetID = NextAvailableSheetID().ToString();

            skills = new SkillsContainer(stats, head.Level, ac.armorPenalty);
            savingThrows = new SavingThrowsContainer(stats.ability("Con").abilityModifier, stats.ability("Dex").abilityModifier, stats.ability("Wis").abilityModifier);
        }

        public static DDSheet LoadSheet(Int32 IDSheet)
        {
            XDocument xmlDoc = XDocument.Load(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));

            XElement XSheet = (from q in xmlDoc.Descendants("Sheet")
                              where q.Attribute("ID").Value == IDSheet.ToString()
                              select q).First();

            DDSheet DaSheet = new DDSheet();
            DaSheet.SheetID = XSheet.Attribute("ID").Value;

            DaSheet.head.Alignment.Value = XSheet.Element("Head").Element("Alignment").Value;
            DaSheet.head.Class.Value = XSheet.Element("Head").Element("Class").Value;
            DaSheet.head.Deity.Value = XSheet.Element("Head").Element("Deity").Value;
            DaSheet.head.Experience.Value = Int32.Parse(XSheet.Element("Head").Element("Experience").Value);
            DaSheet.head.Level.Value = Int32.Parse(XSheet.Element("Head").Element("Level").Value);
            DaSheet.head.Nom.Value = XSheet.Element("Head").Element("Nom").Value;
            DaSheet.head.PlayerName.Value = XSheet.Element("Head").Element("PlayerName").Value;
            DaSheet.head.Race.Value = XSheet.Element("Head").Element("Race").Value;
            DaSheet.head.Sex.Value = XSheet.Element("Head").Element("Sex").Value;
            DaSheet.head.Size.Value = XSheet.Element("Head").Element("Size").Value;

            DaSheet.combat.MaxHP.Value = Int32.Parse(XSheet.Element("Combat").Element("MaxHP").Value);
            DaSheet.combat.MaxHP.Value = Int32.Parse(XSheet.Element("Combat").Element("currentHP").Value);
            foreach (XElement x in XSheet.Element("Combat").Elements("BAB"))
            {
                DaSheet.combat.baseAttackBonus.BABS.Add(new NumericalField(Int32.Parse(x.Value)));
            }

            foreach (XElement x in XSheet.Element("Combat").Element("Weapons").Elements("Weapon"))
            {
                WeaponContainer w = new WeaponContainer(x.Element("WeaponName").Value, x.Element("Damage").Value, x.Element("Type").Value);
                w.Notes.Value = x.Element("Notes").Value;
                w.Range.Value = x.Element("Range").Value;
                w.WeaponDmgBonus.Value = Int32.Parse(x.Element("WeaponDmgBonus").Value);
                w.Critical.Value = x.Element("Critical").Value;
                DaSheet.combat.Weapons.Add(x.Attribute("ID").Value, w);
            }

            
            return DaSheet;
        }

        public static DDSheet SaveSheet(DDSheet theSheet)
        {
            XDocument xmlDoc = XDocument.Load("/Content/DDpages/Sheets.xml");
            
            XElement Head = new XElement("Head");
            Head.Add(new XElement("Alignment", theSheet.head.Alignment.Value));
            Head.Add(new XElement("Class", theSheet.head.Class.Value));
            Head.Add(new XElement("Deity", theSheet.head.Deity.Value));
            Head.Add(new XElement("Experience", theSheet.head.Experience.Value));
            Head.Add(new XElement("Level", theSheet.head.Level.Value));
            Head.Add(new XElement("Nom", theSheet.head.Nom.Value));
            Head.Add(new XElement("PlayerName", theSheet.head.PlayerName.Value));
            Head.Add(new XElement("Race", theSheet.head.Race.Value));
            Head.Add(new XElement("Sex", theSheet.head.Sex.Value));
            Head.Add(new XElement("Size", theSheet.head.Size.Value));

            XElement Combat = new XElement("Combat");
            Combat.Add(new XElement("currentHP", theSheet.combat.currentHP.Value));
            Combat.Add(new XElement("MaxHP", theSheet.combat.MaxHP.Value));
            foreach (NumericalField b in theSheet.combat.baseAttackBonus.BABS)
            {
                Combat.Add(new XElement("BAB", b.Value));
            }
            XElement Weapons = new XElement("Weapons");
            foreach (KeyValuePair<String, WeaponContainer> w in theSheet.combat.Weapons)
            {
                XElement Weapon = new XElement("Weapon");
                XAttribute A = new XAttribute("ID", w.Key);
                XElement B = new XElement("Critical", w.Value.Critical.Value);
                XElement C = new XElement("Damage", w.Value.Damage.Value);
                XElement D = new XElement("Notes", w.Value.Notes.Value);
                XElement E = new XElement("Range", w.Value.Range.Value);
                XElement F = new XElement("Type", w.Value.Type.Value);
                XElement G = new XElement("WeaponName", w.Value.WeaponName.Value);
                XElement H = new XElement("WeaponDmgBonus", w.Value.WeaponDmgBonus.Value);

                Weapon.Add(A);
                Weapon.Add(B);
                Weapon.Add(C);
                Weapon.Add(D);
                Weapon.Add(E);
                Weapon.Add(F);
                Weapon.Add(G);
                Weapon.Add(H);
                Weapons.Add(Weapon);
            }
            Combat.Add(Weapons);


            XElement AC = new XElement("AC");
            AC.Add(new XElement("ArmorBonus", theSheet.ac.ArmorBonus.Value));
            AC.Add(new XElement("ArmorCheckPenalty", theSheet.ac.ArmorCheckPenalty.Value));
            AC.Add(new XElement("ArmorMaxDex", theSheet.ac.ArmorMaxDex.Value));
            AC.Add(new XElement("ArmorName", theSheet.ac.ArmorName.Value));
            AC.Add(new XElement("armorPenalty", theSheet.ac.armorPenalty.Value));
            AC.Add(new XElement("ArmorWeight", theSheet.ac.ArmorWeight.Value));
            AC.Add(new XElement("BaseAC", theSheet.ac.BaseAC.Value));
            AC.Add(new XElement("DeflectionModifier", theSheet.ac.DeflectionModifier.Value));
            AC.Add(new XElement("MiscModifier", theSheet.ac.MiscModifier.Value));
            AC.Add(new XElement("NaturalArmorModifier", theSheet.ac.NaturalArmorModifier.Value));
            AC.Add(new XElement("SizeModifier", theSheet.ac.SizeModifier.Value));
            AC.Add(new XElement("ShieldBonus", theSheet.ac.ShieldBonus.Value));
            AC.Add(new XElement("ShieldCheckPenalty", theSheet.ac.ShieldCheckPenalty.Value));
            AC.Add(new XElement("ShieldMaxDex", theSheet.ac.ShieldMaxDex.Value));
            AC.Add(new XElement("ShieldName", theSheet.ac.ShieldName.Value));
            AC.Add(new XElement("ShieldWeight", theSheet.ac.ShieldWeight.Value));

            XElement Equipment = new XElement("Equipment");
            Equipment.Add(new XElement("lightWeight", theSheet.equipment.lightWeight.Value));
            Equipment.Add(new XElement("mediumWeight", theSheet.equipment.mediumWeight.Value));
            Equipment.Add(new XElement("heavyWeight", theSheet.equipment.heavyWeight.Value));
            foreach (ItemContainer s in theSheet.equipment.items)
            {
                XElement item = new XElement("item");
                XAttribute A = new XAttribute("name", s.Name.Value);
                XAttribute B = new XAttribute("weight", s.Weight.Value);
                item.Add(A);
                item.Add(B);
                Equipment.Add(item);

            }
            XElement Feats = new XElement("Feats");
            foreach (FeatContainer s in theSheet.feats.feats)
            {
                Feats.Add("FeatName", s.FeatName.Value);
                Feats.Add("FeatDescription", s.FeatDescription.Value);
            }

            XElement Language = new XElement("Language");
            foreach (StringField s in theSheet.language.languages)
            {
                Language.Add("Langue", s.Value);
            }

            XElement Magic = new XElement("Magic");
            Magic.Add(new XElement("ArcaneFailure", theSheet.magic.arcaneFailure.Value));
            Magic.Add(new XElement("School", theSheet.magic.school.Value));
            Magic.Add(new XElement("SpellSave", theSheet.magic.spellSave.Value));

            XElement Stats = new XElement("Stats");
            Stats.Add(new XElement("Initiative", theSheet.stats.baseInitative.Value));
            Stats.Add(new XElement("ModifInitiative", theSheet.stats.miscInitiative.Value));
            Stats.Add(new XElement("Speed", theSheet.stats.Speed.Value));
            foreach (KeyValuePair<String, AbilityContainer> S in theSheet.stats.listAbilities)
            {
                XElement Stat = new XElement("Stat");
                XAttribute A = new XAttribute("ID", S.Key);
                XElement B = new XElement("ArmorCheck", S.Value.baseScore.Value);
                XElement C = new XElement("ArmorCheck", S.Value.tempScore.Value);

                Stat.Add(A);
                Stat.Add(B);
                Stat.Add(C);
                Stats.Add(Stat);
            }


            XElement Skills = new XElement("Skills");
            Skills.Add(new XElement("pointPerLevel", theSheet.skills.pointPerLevel.Value));
            foreach (KeyValuePair<String, SingleSkillContainer> S in theSheet.skills.listeSkill)
            {
                XElement Skill = new XElement("Skill");
                XAttribute A = new XAttribute("ID", S.Key);
                XElement B = new XElement("ArmorCheck", S.Value.ArmorCheck.Value);
                XElement C = new XElement("classSkill", S.Value.classSkill.Value);
                XElement D = new XElement("miscBonus", S.Value.miscBonus.Value);
                XElement E = new XElement("ranksBonus", S.Value.ranksBonus.Value);
                XElement F = new XElement("UntrainedSkill", S.Value.UntrainedSkill.Value);

                Skill.Add(A);
                Skill.Add(B);
                Skill.Add(C);
                Skill.Add(D);
                Skill.Add(E);
                Skill.Add(F);
                Skills.Add(Skill);
            }

            XElement Spells = new XElement("Spells");
            foreach (KeyValuePair<String, SpellContainer> S in theSheet.spells.spells)
            {
                XElement Spell = new XElement("Spell");
                XAttribute A = new XAttribute("ID", S.Key);
                XElement B = new XElement("Name", S.Value.SpellName.Value);
                XElement C = new XElement("Description", S.Value.SpellDescription.Value);
                XElement D = new XElement("Range", S.Value.Range.Value);
                XElement E = new XElement("School", S.Value.SpellSchool.Value);
                Spell.Add(A);
                Spell.Add(B);
                Spell.Add(C);
                Spell.Add(D);
                Spell.Add(E);
                Spells.Add(Spell);
            }


            XElement SavingThrows = new XElement("SavingThrows");
            foreach (SavingThrowContainer S in theSheet.savingThrows.listAbilities.Values)
            {
                XElement SavingThrow = new XElement("SavingThrow");
                XAttribute A = new XAttribute("name",S.SavingThrowName.Value);
                XElement B = new XElement("magicBonus", S.magicalBonus.Value);
                XElement C = new XElement("baseBonus", S.baseSave.Value);
                XElement D = new XElement("miscBonus", S.miscBonus.Value);
                SavingThrow.Add(A);
                SavingThrow.Add(B);
                SavingThrow.Add(C);
                SavingThrow.Add(D);
                SavingThrows.Add(SavingThrow);
            }
            XElement Sheet = new XElement("Sheet");
            XAttribute ID = new XAttribute("ID", theSheet.SheetID);
            Sheet.Add(Head);
            Sheet.Add(Combat);
            Sheet.Add(AC);
            Sheet.Add(Equipment);
            Sheet.Add(Feats);
            Sheet.Add(Language);
            Sheet.Add(Magic);
            Sheet.Add(Stats);
            Sheet.Add(Skills);
            Sheet.Add(Spells);
            Sheet.Add(SavingThrows);
            xmlDoc.Element("Sheets").Add(Sheet);
            xmlDoc.Save(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));
            return theSheet;
        }

        public static void DestroySheet(string IDSheet)
        {
            XDocument xmlDoc = XDocument.Load(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));

            XElement query = (from q in xmlDoc.Descendants("Sheet")
                                        where q.Attribute("ID").Value == IDSheet
                                        select q).First();
            query.Remove();
            xmlDoc.Save(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));
        }

        public static int NextAvailableSheetID()
        {
            XDocument xmlDoc = XDocument.Load(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));
            return (xmlDoc.Descendants("Sheet").Count() + 1);
        }

        public static List<PlayerIndex> playerSheetList()
        {
            List<PlayerIndex> retour = new List<PlayerIndex>();
            XDocument xmlDoc = XDocument.Load(HostingEnvironment.MapPath("/Content/DDpages/Sheets.xml"));
            IEnumerable<XElement> i = from q in xmlDoc.Descendants("Sheet")
                                      select q;
            foreach (XElement a in i)
            {
                PlayerIndex p = new PlayerIndex();
                p.ID = a.Attribute("ID").Value;
                p.playerName = a.Element("Head").Element("PlayerName").Value;
                retour.Add(p);
            }
            return retour;
        }
    }
    public struct PlayerIndex
    {
        public String ID;
        public String playerName;
    }
}